//
//  XQPopupAnimView.m
//  JoinPeso
//
//  Created by 小琦 on 2024/11/21.
//

#import "XQPopupAnimView.h"
#import "UIView+DDAdd.h"

@interface XQPopupAnimView ()<UIGestureRecognizerDelegate>

@property (nonatomic, strong) UIView *customView;
@property (nonatomic, strong) UIView *backgroundView;
@property (nonatomic, strong) UIView *shadowView;

@end

@implementation XQPopupAnimView

- (instancetype)initWithAnimationType:(XQPopupAnimationType)animationType customView:(UIView *)customView {
    if (self = [super initWithFrame:[UIScreen mainScreen].bounds]) {
        
        _animationType = animationType;
        _customView = customView;
        _duration = 0.3f;
        _offset = 0.f;
        _radius = 8.f;
        _hideWhenClickSelf = NO;
        _hideWhenClickOffset = YES;
        _hideWhenClickOutside = YES;
        _canClickOutside = NO;
        
        [self configureUI];
        [self configureGesture];
    }
    return self;
}

- (void)showInView:(UIView * _Nullable)view completion:(void (^)(void))aCompletionBlock {
    [self showInView:view timingParameters:nil completion:aCompletionBlock];
}

- (void)showInView:(UIView * _Nullable)view timingParameters:(id<UITimingCurveProvider> _Nullable)timingParameters completion:(void (^)(void))aCompletionBlock {
    
    [view addSubview:self];
    [self setFrame:view.bounds];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self layoutRadius];
    });
    
    [self makeTransform];
    [self makeTransformAnim:NO timingParameters:timingParameters completion:aCompletionBlock];
    if (self.needCover) {
        [self makeBackgroundAnim:NO];
    }
}

- (void)hideAndCompletion:(void(^)(void))aCompletionBlock {
    [self makeTransformAnim:YES timingParameters:nil completion:aCompletionBlock];
    if (self.needCover) {
        [self makeBackgroundAnim:YES];
    }
}

- (void)makeTransformAnim:(BOOL)isHidden timingParameters:(id<UITimingCurveProvider>)timingParameters completion:(void (^)(void))aCompletionBlock {
    
    CGPoint point1 = CGPointMake(0.42, 0);
    CGPoint point2 = CGPointMake(0.58, 1);
    if (self.animationType != XQPopupAnimationCenter) {
        point1 = CGPointMake(0.46, 0);
        point2 = CGPointMake(0.74, 0.99);
        
        if (isHidden) {
            if (self.animationType == XQPopupAnimationTop) {
                point1 = CGPointMake(0, 0);
                point2 = CGPointMake(0.58, 1);
            } else if (self.animationType == XQPopupAnimationBottom) {
                point1 = CGPointMake(0.25, 0.1);
                point2 = CGPointMake(0.25, 1);
            }
        }
    }
    
    if (@available(iOS 10.0, *)) {
        UIViewPropertyAnimator *anim;
        if (timingParameters) {
            anim = [[UIViewPropertyAnimator alloc] initWithDuration:self.duration
                                                   timingParameters:timingParameters];
        } else {
            anim = [[UIViewPropertyAnimator alloc] initWithDuration:self.duration
                                                      controlPoint1:point1
                                                      controlPoint2:point2
                                                         animations:nil];
        }
        [anim addAnimations:^{
            if (isHidden) {
                [self makeTransform];
            } else {
                [self makeTransformIdentity];
            }
        }];
        [anim addCompletion:^(UIViewAnimatingPosition finalPosition) {
            if (finalPosition == UIViewAnimatingPositionEnd) {
                if (isHidden) {
                    [self removeFromSuperview];
                }
                if (aCompletionBlock) {
                    aCompletionBlock();
                }
            }
        }];
        [anim startAnimation];
    } else {
        // Fallback on earlier versions
    }
}

- (void)makeBackgroundAnim:(BOOL)isHidden {
    UIColor *color = [UIColor blackColor];
    CGFloat  start = isHidden ? 0.6f : 0.f;
    CGFloat  end   = isHidden ? 0.f  : 0.6f;
    
    self.backgroundView.backgroundColor = [color colorWithAlphaComponent:start];
    if (@available(iOS 10.0, *)) {
        UIViewPropertyAnimator *anim = [[UIViewPropertyAnimator alloc] initWithDuration:self.duration
                                                                          controlPoint1:CGPointMake(0.24, 0)
                                                                          controlPoint2:CGPointMake(0.58, 1)
                                                                             animations:^{
            self.backgroundView.backgroundColor = [color colorWithAlphaComponent:end];
        }];
        [anim startAnimation];
    } else {
        // Fallback on earlier versions
    }
}

- (void)makeTransform {
    if (self.animationType == XQPopupAnimationCenter) {
        self.customView.transform = CGAffineTransformMakeScale(.1f, .1f);
        self.customView.alpha = 0.f;
        
    } else {
        CGSize size = self.customView.bounds.size;
        if (CGSizeEqualToSize(size, CGSizeZero)) {
            size = [self.customView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
        }
        CGFloat offsetX = 0, offsetY = 0;
        if (self.animationType == XQPopupAnimationLeft || self.animationType == XQPopupAnimationRight) {
            offsetX = size.width + self.transformOffset;
            if (self.animationType == XQPopupAnimationLeft) offsetX *= -1;
            
        } else {
            offsetY = size.height + self.transformOffset;
            if (self.animationType == XQPopupAnimationTop) offsetY *= -1;
        }
        self.customView.transform = CGAffineTransformMakeTranslation(offsetX, offsetY);
        self.shadowView.transform = CGAffineTransformMakeTranslation(offsetX, offsetY);
    }
}

- (void)makeTransformIdentity {
    if (self.animationType == XQPopupAnimationCenter) {
        self.customView.transform = CGAffineTransformMakeScale(1.f, 1.f);
        self.customView.alpha = 1.f;
        
    } else {
        self.customView.transform = CGAffineTransformIdentity;
        self.shadowView.transform = CGAffineTransformIdentity;
    }
}

#pragma mark - Click Method
- (void)tap:(UIGestureRecognizer *)tap {
    [self hideAndCompletion:^{
        if (self.clickHandle) {
            self.clickHandle();
        }
    }];
}

#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if (!self.hideWhenClickSelf) {
        if ([touch.view isDescendantOfView:self.customView]) {
            return NO;
        }
    }
    if (!self.hideWhenClickOutside) {
        if ([touch.view isDescendantOfView:self.backgroundView]) {
            return NO;
        }
    }
    return YES;
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    if (self.canClickOutside) {
        if (CGRectContainsPoint(self.customView.frame, point)) {
            return YES;
        }
        return NO;
    } else {
        if (!self.hideWhenClickOffset) {
            if (CGRectContainsPoint(self.backgroundView.frame, point)) {
                return YES;
            }
            return NO;
        }
        return [super pointInside:point withEvent:event];
    }
}

#pragma mark - Setter
- (void)setOffset:(CGFloat)offset {
    _offset = offset;
    
    [self setNeedsLayout];
}

- (void)setAnimationType:(XQPopupAnimationType)animationType {
    _animationType = animationType;
    
    [self layoutFrame];
    if (self.makeCustomConstraints) {
        self.makeCustomConstraints(self, self.customView);
        
    } else if (_customHeight != 0) {
        [self layoutCustomFrame];
    }
}

- (void)setCustomHeight:(CGFloat)customHeight {
    _customHeight = customHeight;
    
    if (self.makeCustomConstraints) {
        self.makeCustomConstraints(self, self.customView);
        
    } else {
        [self layoutCustomFrame];
    }
}

- (void)setHideWhenClickOffset:(BOOL)hideWhenClickOutside {
    _hideWhenClickOffset = hideWhenClickOutside;
    
    [self configureGesture];
}

- (void)setMakeCustomConstraints:(void (^)(XQPopupAnimView *, UIView *))customMakeConstraints {
    _makeCustomConstraints = customMakeConstraints;
    
    if (customMakeConstraints) {
        if (self.customView.superview) {
            customMakeConstraints(self,self.customView);
        }
    }
}

#pragma mark - Other
- (void)configureUI {
    self.shadowView.layer.shadowPath    = self.customView.layer.shadowPath;
    self.shadowView.layer.shadowColor   = self.customView.layer.shadowColor;
    self.shadowView.layer.shadowRadius  = self.customView.layer.shadowRadius;
    self.shadowView.layer.shadowOffset  = self.customView.layer.shadowOffset;
    self.shadowView.layer.shadowOpacity = self.customView.layer.shadowOpacity;
    
    self.shadowView.layer.cornerRadius  = self.radius;
    self.shadowView.backgroundColor     = self.customView.backgroundColor;
    
    [self addSubview:self.backgroundView];
    [self.backgroundView addSubview:self.shadowView];
    [self.backgroundView addSubview:self.customView];
    
    [self.shadowView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.top.bottom.right.equalTo(self.customView);
    }];
}

- (void)layoutFrame {
    CGFloat y = self.animationType == XQPopupAnimationTop ? _offset : 0.f;
    CGFloat h = self.bounds.size.height - _offset;
    
    CGRect f = self.bounds;
    f.origin.y = y;
    f.size.height = h;
    self.backgroundView.frame = f;
}

- (void)layoutCustomFrame {
    CGFloat width = self.backgroundView.bounds.size.width;
    CGFloat height = self.backgroundView.bounds.size.height;
    
    CGFloat w = self.customView.frame.size.width;
    CGFloat h = _customHeight;
    CGFloat x = (width - w) * 0.5;
    CGFloat y = 0.f;
    if (self.animationType == XQPopupAnimationCenter) {
        y = (height - _customHeight) * 0.5;
    } else if (self.animationType == XQPopupAnimationBottom) {
        y = height - _customHeight;
    }
    self.customView.frame = CGRectMake(x, y, w, h);
}

- (void)layoutRadius {
    if (self.radius > 0) {
        if (self.customView.size.width != 0 && self.customView.size.height != 0) {
            UIRectCorner corner = UIRectCornerAllCorners;
            if (_animationType == XQPopupAnimationTop) {
                corner = UIRectCornerBottomLeft | UIRectCornerBottomRight;
            } else if (_animationType == XQPopupAnimationBottom) {
                corner = UIRectCornerTopLeft | UIRectCornerTopRight;
            }
            [self.customView setRoundingCorners:corner cornerRadii:CGSizeMake(self.radius, self.radius)];
        }
    }
}

- (void)layoutSubviews {
    [super layoutSubviews];
    
    [self layoutFrame];
    if (self.customHeight != 0 && !self.makeCustomConstraints) {
        [self layoutCustomFrame];
    }
}

- (void)configureGesture {
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
    tap.delegate = self;
    [self addGestureRecognizer:tap];
}

#pragma mark - Getter
- (UIView *)backgroundView {
    if (!_backgroundView) {
        _backgroundView = [[UIView alloc] initWithFrame:self.bounds];
        _backgroundView.layer.masksToBounds = YES;
    }
    return _backgroundView;
}

- (UIView *)shadowView {
    if (!_shadowView) {
        _shadowView = [[UIView alloc] init];
        _shadowView.backgroundColor = [UIColor clearColor];
    }
    return _shadowView;
}


@end
